/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.connect5.intervals;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;
import org.jfonia.connect5.basics.ValueNode;
import org.jfonia.connect5.basics.Node;
import org.jfonia.connect5.basics.Observer;

/**
 * This class warns his observers if element is added or removed.
 * When the child intervals themself are observable they will also be warned
 * when a child is changed
 * Written by Jannes Plyson for an LinkedIntIntervalList, modified to
 * work with a LinkedDoubleIntervalList too
 * @author Jannes Plyson, Rik Bauwens
 */
public class ObservableLinkedDoubleIntervalList extends LinkedDoubleIntervalList implements Observer
{
        private Set<ListObserver> observers = new LinkedHashSet<ListObserver>();
        private HashMap<ValueNode,Interval> endToIntervalMap = new HashMap<ValueNode, Interval>();

	public void addObserver(ListObserver o)
	{
		if (!observers.contains(o))
			observers.add(o);
	}

	public boolean containsObserver(ListObserver o)
	{
		return observers.contains(o);
	}

	public void removeObserver(ListObserver o)
	{
		observers.remove(o);
	}

        @Override
        public Interval<Double> add(Interval<Double> ts)
        {
            Interval<Double> val = super.insert(size(),ts);
            val.getEndNode().addObserver(this);
            endToIntervalMap.put(val.getEndNode(), val);
            for(ListObserver observer : observers)
                    observer.intervalAdded(val);
            return val;
        }

        @Override
        public Interval<Double> insert(int pos, Interval<Double> val)
        {
                Interval<Double> interval = super.insert(pos,val);
                val.getEndNode().addObserver(this);
                endToIntervalMap.put(val.getEndNode(), val);
                for(ListObserver observer : observers)
                        observer.intervalAdded(val);
                return interval;
        }

    @Override
    public Interval<Double> remove(int i)
    {
            Interval<Double> interval = super.remove(i);
            endToIntervalMap.remove(interval.getEndNode());
            interval.getEndNode().removeObserver(this);
            if(interval instanceof Node)
                    ((Node)interval).addObserver(this);
            for(ListObserver observer : observers)
                    observer.intervalRemoved(interval,i);
            return interval;
    }

    public void onNotify(Object source) {
        Interval interval = endToIntervalMap.get((ValueNode)source);
        if(interval != null)
        {
                for(ListObserver observer : observers)
                        observer.intervalEndChanged(interval);
        }
    }
}
